package com.example.common.base

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import java.io.File

/**
 *  Created by LC on 2025/4/22.
 *  ViewModel基准类,泛型为具体实现的意图
 */
abstract class BaseViewModel<uiIntent : UiIntent> : ViewModel() {
    //存放意图的管道(频道) UNLIMITED 代表数量没有最小值
    private val _uiIntent = Channel<UiIntent> { Channel.UNLIMITED }

    //可变的状态,用于更新UI,默认值是读取中
    //由于是哥private修饰的,不允许外部修改,所以需要一个对外暴露的方法
    var _state = MutableStateFlow<UiState>(UiState.OnLoading)
    val state: StateFlow<UiState>
        get() = _state

    //初始化
    init {
        viewModelScope.launch {
            //会将所有的意图转化为流,用于接收
            _uiIntent.receiveAsFlow().collect {
                handleIntent(it)
            }
        }
    }

    //所有继承当前BaseViewModel的类,都需要实现该方法,用来处理对应的意图
    //比如登录的Intent,需要处理登录的意图
    abstract fun handleIntent(it: UiIntent)

    //发送意图
    //当前页面需要有发送请求数据的时候,需要调用该方法,并传入一个意图
    fun sendIntent(intent: UiIntent) {
        viewModelScope.launch {
            _uiIntent.send(intent)
        }
    }

    fun httpRequest(request: Flow<Res<Any>>, type: StateType = StateType.DEFAULT) {
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch {
                    Log.e("TagA", "error:${it.message}")
                }.collect {
                    if (it.code == 200) {
                        _state.value = UiState.OnSuccess(it.data, type)
                    } else {
                        _state.value = UiState.OnError(it.msg)
                    }
                }
        }
    }

    //下载的方法
    fun download(url: String, file: File) {
        viewModelScope.launch {
            DownloadUtils.download(url, file)
                .flowOn(Dispatchers.IO)
                .catch {
                    Log.e("TagA", "下载错误:${it.message}")
                }.collect {
                    _state.value = it
                }
        }
    }

    //数据库请求数据的方法
    fun roomRequest(request: Flow<Any>, type: StateType = StateType.REGISTER) {
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch {
                    Log.e("TagA", "数据库错误:${it.message}")
                }.collect {
                    if (it != null) {
                        _state.value = UiState.OnSuccess(it, type)
                    } else {
                        _state.value = UiState.OnError("数据库错误,查询为空")
                    }
                }
        }
    }

    //参数是文件夹,在kotlin或者Android中,File不光代表一个文件,也可以代表是一个文件夹
    fun scanFile(file: File) {
        viewModelScope.launch {
            try {
                //查找文件夹中所有的文件,形成一个list
                val files = file.listFiles()
                //声明一个计划额,集合中包含自己创建的数据类型,数据类型中包含文件名和文件路径
                val list = mutableListOf<LocalEntity>()
                for (i in files) {
                    //循环添加文件夹中所有的文件到集合中
                    list.add(LocalEntity(i.name, i.absolutePath))
                }
                _state.value = UiState.OnSuccess(list)
            } catch (e: Exception) {
                _state.value = UiState.OnError(e.message.toString())
            }
        }
    }
}

//标记本地文件的数据类
data class LocalEntity(val fileName: String, val filePath: String)